#include <math.h>
#include "scr_enemy_behavior_blinky.h"
#include "scr_enemy_behavior.h"
#include "scr_enemy.h"
#include "scr_game_data.h"
#include "scr_game.h"
#include "scr_basic_sprite.h"
#include "scr_game_data.h"
#include "scr_marine.h"
#include "scr_math.h"

#define SCR_ENEMY_TIME_BLINKY 33
#define SCR_ENEMY_TURN_SPEED_BLINKY 384
#define SCR_ENEMY_WALK_SPEED_BLINKY (1 << 12)
#define SCR_ENEMY_LIFE_BLINKY 100

void SCREnemyBehaviorBlinky::Initialize(SCREnemy* Enemy)
{
	Enemy->m_Behavior = this;
	SCRMarine* pMarine = SCRGame::GetInstance()->GetSharedData()->GetMarine();

	bool Retry = false;
	do
	{
		Retry = false;
		int RandomX = rand() % SCR_MAP_SIZE_X;
		int RandomY = rand() % SCR_MAP_SIZE_Y;
		int Distance2 = ((pMarine->GetX() - RandomX) * (pMarine->GetX() - RandomX)) +
			((pMarine->GetY() - RandomY) * (pMarine->GetY() - RandomY));
		if (SCRGame::GetInstance()->GetSharedData()->m_CheckMapAA[RandomX >> 5][RandomY >> 5])
		{
			Retry = true;
		}
		else if (Distance2 < 400 * 400)
		{
			Retry = true;
		}
		else
		{
			SCRGame::GetInstance()->GetSharedData()->m_CheckMapAA[RandomX >> 5][RandomY >> 5] = Enemy->m_Index;
			Enemy->m_X = FXIntToFX(RandomX);
			Enemy->m_Y = FXIntToFX(RandomY);
			Enemy->m_Active = 1;
			Enemy->m_Random = rand();
			Enemy->m_DecisionTime = SCR_ENEMY_TIME_BLINKY;
			Enemy->m_Heading = rand() % (1 << 16);
			Enemy->m_Life = SCR_ENEMY_LIFE_BLINKY;
		}
	}
	while (Retry);
}

void SCREnemyBehaviorBlinky::Update(SCREnemy* Enemy, const int& Delta)
{
	Enemy->m_DecisionTime -= Delta;
	if (Enemy->m_DecisionTime <= 0)
	{
		Enemy->m_DecisionTime = SCR_ENEMY_TIME_BLINKY + (rand() % SCR_ENEMY_TIME_BLINKY);
	}

	SCRGameData* pSharedData = SCRGame::GetInstance()->GetSharedData();
	SCRMarine* pMarine = pSharedData->GetMarine();
	int DiffX = pMarine->GetFixedX() - Enemy->m_X;
	int DiffY = pMarine->GetFixedY() - Enemy->m_Y;
	float TargetAngle = atan2f((float)DiffX, (float)-DiffY);
	int FixedTargetAngle = (int)((float)FX32_TABLE_SIZE * (float)(TargetAngle / (PI * 2.0)));
	int NormalizedAngle = (Enemy->m_Heading - FixedTargetAngle) & FX32_TABLE_MASK;
	if (NormalizedAngle > (FX32_TABLE_SIZE >> 1))
	{
		Enemy->m_Heading += SCR_ENEMY_TURN_SPEED_BLINKY;
	}
	else
	{
		Enemy->m_Heading -= SCR_ENEMY_TURN_SPEED_BLINKY;
	}
	Enemy->m_Heading = Enemy->m_Heading & FX32_TABLE_MASK;

	FX32 NewPosX = Enemy->m_X + FXMul(SCRMath::FXSin(Enemy->m_Heading), SCR_ENEMY_WALK_SPEED_BLINKY);
	FX32 NewPosY = Enemy->m_Y - FXMul(SCRMath::FXCos(Enemy->m_Heading), SCR_ENEMY_WALK_SPEED_BLINKY);

	if (NewPosX < 0)
	{
		NewPosX = 0;
	}

	if (NewPosX > SCR_MAP_SIZE_X << FX32_SHIFT)
	{
		NewPosX = SCR_MAP_SIZE_X << FX32_SHIFT;
	}

	if (NewPosY < 0)
	{
		NewPosY = 0;
	}

	if (NewPosY > SCR_MAP_SIZE_Y << FX32_SHIFT)
	{
		NewPosY = SCR_MAP_SIZE_Y << FX32_SHIFT;
	}

	int CheckIndex = pSharedData->m_CheckMapAA[FXFXToInt(NewPosX) >> 5][FXFXToInt(NewPosY) >> 5];
	if (0 == CheckIndex || CheckIndex == Enemy->m_Index)
	{
		pSharedData->m_CheckMapAA[FXFXToInt(NewPosX) >> 5][FXFXToInt(NewPosY) >> 5] = Enemy->m_Index;
		Enemy->m_X = NewPosX;
		Enemy->m_Y = NewPosY;
	}
	else
	{
		if (Enemy->m_Random % 2)
		{
			Enemy->m_Heading -= SCR_ENEMY_TURN_SPEED_BLINKY * 2;
		}
		else
		{
			Enemy->m_Heading += SCR_ENEMY_TURN_SPEED_BLINKY * 2;
		}
	}
}

void SCREnemyBehaviorBlinky::Render(SCREnemy* Enemy, const int& Delta)
{
	const int Angle = Enemy->m_Heading >> 12;
	SCRGame::GetInstance()->GetSharedData()->GetEnemy()->Draw(FXFXToInt(Enemy->m_X), FXFXToInt(Enemy->m_Y), 0, Angle);
}
